package tests;




import java.util.ArrayList;
import java.util.List;


import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import command.Command;
import command.If;
import command.Move;
import command.Sequence;
import command.Shoot;
import command.Turn;
import command.While;
import condition.EnergyAtLeast;
import condition.Not;
import condition.WallCondition;

import roborally.Board;
import roborally.Direction;
import roborally.EnergyAmount;
import roborally.EnergyUnit;
import roborally.Orientation;
import roborally.Position;

import elements.Robot;
import gui.Facade;

/**
 * @version	3.0
 * @author 	Lies Tambeur 	r0264469	2Bcwsbbh
 * @author	Eline Vanrykel	r0264543	2Bcwselt
 * 
 */
public class EntryTest {
	
	/**
	 * Set up an immutable test fixture.
	 * @post   The robot defaultRobot references a new
	 *         robot with position (0,0), energy 0 and orientation 0.
	 */
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		
	}
	
	/**
	 * Set up a mutable test fixture.
	 * 
	 * @post   The variable robot33Orient0Energy20000 references a new
	 *         robot with with position (3,3), energy 20000 and orientation 0.
	 * @post   The variable robot82Orient3Energy8000 references a new
	 *         robot with  position (8,2), energy 8000 and orientation 3.
	 */
	@Before
	public void setUp() throws Exception {
		facade = new Facade();
		
		command1 = new While(new EnergyAtLeast(new EnergyAmount(1000,EnergyUnit.WATTSECONDS)), new Move());
		
		List<Command> comm = new ArrayList<Command>();
		comm.add(new Turn(Direction.CLOCKWISE));
		comm.add(new Move());
		command2 = new If(new Not(new WallCondition()), new Sequence(comm), new Move());
		thousandEnergy = new EnergyAmount(1000,EnergyUnit.WATTSECONDS);
	}
	
	private Facade facade;
	private Command command1;
	private Command command2;
	private EnergyAmount thousandEnergy;
	
	@Test
	public void executeIf(){
		Board board9 = new Board(9,9);
		facade.addBoard(board9);
		Robot robot = new Robot();
		board9.putElement(new Position(1, 1), robot);
		command2.execute(robot);
		assertEquals(new Position(1,2), robot.getPosition());
		assertEquals(Orientation.DOWN, robot.getOrientation());
		board9.terminate();
	}
	
	@Test
	public void executeWhile(){
		Board board9 = new Board(9,9);
		facade.addBoard(board9);
		Robot robot = new Robot(Orientation.RIGHT,thousandEnergy);
		board9.putElement(new Position(1, 1), robot);
		command1.execute(robot);
		assertEquals(new Position(2,1), robot.getPosition());
		assertEquals(Orientation.RIGHT, robot.getOrientation());
		board9.terminate();
	}
	
	
	@Test 
	public void executeSingleStepIf(){
		Board board9 = new Board(9,9);
		facade.addBoard(board9);
		Robot robot = new Robot(Orientation.RIGHT,thousandEnergy.multiplyAndReturn(2));
		board9.putElement(new Position(1, 1), robot);
		
		List<Command> comm = new ArrayList<Command>();
		comm.add(new Move());
		comm.add(new Turn(Direction.CLOCKWISE));
		Command command = new If(new EnergyAtLeast(thousandEnergy.multiplyAndReturn(1.8)), new Sequence(comm), new Turn(Direction.COUNTERCLOCKWISE));
		
		command.executeSingleStep(robot);
		
		assertEquals(thousandEnergy.multiplyAndReturn(1.5), robot.getEnergy());
		assertEquals(Orientation.RIGHT, robot.getOrientation());
		assertEquals(new Position(2,1), robot.getPosition());
		
		command.executeSingleStep(robot);
		
		assertEquals(thousandEnergy.multiplyAndReturn(1.4), robot.getEnergy());
		assertEquals(Orientation.DOWN, robot.getOrientation());
		assertEquals(new Position(2,1), robot.getPosition());
		
		command.executeSingleStep(robot);
		
		assertEquals(thousandEnergy.multiplyAndReturn(1.4), robot.getEnergy());
		assertEquals(Orientation.DOWN, robot.getOrientation());
		assertEquals(new Position(2,1), robot.getPosition());
	}
	
	@Test 
	public void executeSingleStepSeq(){
		Board board9 = new Board(9,9);
		facade.addBoard(board9);

		List<Command> com = new ArrayList<Command>();
		com.add(new Shoot());
		List<Command> co = new ArrayList<Command>();
		co.add(new Move());
		co.add(new Turn(Direction.CLOCKWISE));
		com.add(new If(new EnergyAtLeast(thousandEnergy.multiplyAndReturn(1.8)), new Sequence(co), new Turn(Direction.COUNTERCLOCKWISE)));
		Command command1 = new Sequence(com);
		Robot robot1 = new Robot(Orientation.DOWN,thousandEnergy.multiplyAndReturn(1.9));
		board9.putElement(new Position(1, 1), robot1);
		
		command1.executeSingleStep(robot1);
		
		assertEquals(thousandEnergy.multiplyAndReturn(0.9), robot1.getEnergy());
		assertEquals(Orientation.DOWN, robot1.getOrientation());
		assertEquals(new Position(1,1), robot1.getPosition());
		
		command1.executeSingleStep(robot1);
		
		assertEquals(thousandEnergy.multiplyAndReturn(0.8), robot1.getEnergy());
		assertEquals(Orientation.RIGHT, robot1.getOrientation());
		assertEquals(new Position(1,1), robot1.getPosition());
	}
	
	@Test 
	public void executeSingleStepWhile(){
		Board board9 = new Board(9,9);
		facade.addBoard(board9);

		List<Command> co = new ArrayList<Command>();
		co.add(new Move());
		co.add(new Turn(Direction.CLOCKWISE));
		Command command1 = new While(new EnergyAtLeast(thousandEnergy), new Sequence(co));
		Robot robot1 = new Robot(Orientation.DOWN,thousandEnergy.multiplyAndReturn(2));
		board9.putElement(new Position(1, 1), robot1);
		
		command1.executeSingleStep(robot1);
		
		assertEquals(thousandEnergy.multiplyAndReturn(1.5), robot1.getEnergy());
		assertEquals(Orientation.DOWN, robot1.getOrientation());
		assertEquals(new Position(1,2), robot1.getPosition());
		
		command1.executeSingleStep(robot1);
		
		assertEquals(thousandEnergy.multiplyAndReturn(1.4), robot1.getEnergy());
		assertEquals(Orientation.LEFT, robot1.getOrientation());
		assertEquals(new Position(1,2), robot1.getPosition());
		
		command1.executeSingleStep(robot1);
		
		assertEquals(thousandEnergy.multiplyAndReturn(0.9), robot1.getEnergy());
		assertEquals(Orientation.LEFT, robot1.getOrientation());
		assertEquals(new Position(0,2), robot1.getPosition());
		
		command1.executeSingleStep(robot1);
		
		assertEquals(thousandEnergy.multiplyAndReturn(0.8), robot1.getEnergy());
		assertEquals(Orientation.UP, robot1.getOrientation());
		assertEquals(new Position(0,2), robot1.getPosition());
	}

	@Test
	public void executeSingleStep(){
		Board board9 = new Board(9,9);
		facade.addBoard(board9);
		
		Robot robot = new Robot(Orientation.UP, thousandEnergy.multiplyAndReturn(3));
		board9.putElement(new Position(1, 1), robot);
		
		List<Command> co = new ArrayList<Command>();
		co.add(new Shoot());
		List<Command> com = new ArrayList<Command>();
		com.add(new Move());
		com.add(new Turn(Direction.CLOCKWISE));
		co.add(new While(new EnergyAtLeast(thousandEnergy), new Sequence(com)));
		co.add(new If(new EnergyAtLeast(thousandEnergy.multiplyAndReturn(0.9)), new Move(), new Turn(Direction.COUNTERCLOCKWISE)));
		Command command = new Sequence(co);
		//1
		command.executeSingleStep(robot);		
		assertEquals(thousandEnergy.multiplyAndReturn(2), robot.getEnergy());
		assertEquals(Orientation.UP, robot.getOrientation());
		assertEquals(new Position(1,1), robot.getPosition());
		//2
		command.executeSingleStep(robot);		
		assertEquals(thousandEnergy.multiplyAndReturn(1.5), robot.getEnergy());
		assertEquals(Orientation.UP, robot.getOrientation());
		assertEquals(new Position(1,0), robot.getPosition());
		//3
		command.executeSingleStep(robot);		
		assertEquals(thousandEnergy.multiplyAndReturn(1.4), robot.getEnergy());
		assertEquals(Orientation.RIGHT, robot.getOrientation());
		assertEquals(new Position(1,0), robot.getPosition());
		//4
		command.executeSingleStep(robot);		
		assertEquals(thousandEnergy.multiplyAndReturn(0.9), robot.getEnergy());
		assertEquals(Orientation.RIGHT, robot.getOrientation());
		assertEquals(new Position(2,0), robot.getPosition());
		//5
		command.executeSingleStep(robot);		
		assertEquals(thousandEnergy.multiplyAndReturn(0.8), robot.getEnergy());
		assertEquals(Orientation.DOWN, robot.getOrientation());
		assertEquals(new Position(2,0), robot.getPosition());
		//6
		command.executeSingleStep(robot);		
		assertEquals(thousandEnergy.multiplyAndReturn(0.7), robot.getEnergy());
		assertEquals(Orientation.RIGHT, robot.getOrientation());
		assertEquals(new Position(2,0), robot.getPosition());
	}
	
	@Test
	public final void StringTestEntry(){
		Facade fac = new Facade();
		Robot robot = new Robot();
		Board board = new Board(200,300);
		fac.addBoard(board);
		fac.loadProgramFromFile(robot, "C:\\Users\\Eline\\testAllEntries.txt");
		fac.saveProgramToFile(robot, "C:\\Users\\Eline");
		assertEquals(0, fac.loadProgramFromFile(robot, "C:\\Users\\Eline\\programOfRobot.txt"));
		
	}
	
	
	

}

